Author
Name: Stephen Kamau
Email: stiveckamash@gmail.com
0705698768.
OBJECT DETECTION(R-CNN, Region-Based Convolutional Neural Networks), Fast R-CNN, YOLO (You Only Look Once) and Detectron by FB reseachCheck on the same Implimentation using YoloV6, and YoloV7(latest yolo models).Training a Yolo Model is very Easy, the Bigger part comes when the dataset is not in the format required. Yolo expects the labels (Bounding Box Information) to be in a txt format with the same name as the Image.
The Demo will showcase how to come up with these TXT files for a particular Image as It is the main part for the demo.
For your Own Annotation, you can check ROBOFLOW PLATFORM. CHECK SAMPLE HERE
Mostly, you are training a model to identify objects or not hence you need to have annotation for each image except the background images (It does not have labels). -It is also recommended to add up to 10% background images, to reduce false-positives errors. In this demo, i did not have any background image and incase for your test, you can add them.
Background images are images with no objects that are added to a dataset to reduce False Positives (FP). We recommend about 0-10% background images to help reduce FPs (COCO has 1000 background images for reference, 1% of the total). No labels are required for background images. : linkfrom google.colab import drive
drive.mount('/content/drive')
Mounted at /content/drive
# import som modules
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.model_selection import GroupKFold
from tqdm.notebook import tqdm
from glob import glob #extract content from dirs
import shutil, os #making dirs and copy files
import cv2 #image reading/manipulation
import warnings
warnings.filterwarnings("ignore");
# Path to where the data is stored
DATA_DIR ="/content/drive/MyDrive/FIRE"
# read labels
df = pd.read_csv(f"{DATA_DIR}/labels.csv")
# check shape
df.shape
(4562, 8)
# columns
df.columns
Index(['file_id', 'img_name', 'xmax', 'ymax', 'xmin', 'ymin', 'width',
'height'],
dtype='object')
# if there is any null
df.isna().sum()
file_id 0 img_name 0 xmax 0 ymax 0 xmin 0 ymin 0 width 0 height 0 dtype: int64
Exploring a sample Image with its Bbox information.
# check the number of files we have
df.file_id.nunique()
2187
df.file_id.value_counts()
WEBFire997 5
WEBFire970 5
WEBFire941 5
WEBFire993 5
WEBFire1014 5
..
WEBFire1728 1
WEBFire1070 1
WEBFire1218 1
WEBFire1232 1
new_fire_61 1
Name: file_id, Length: 2187, dtype: int64
sample_row = df.iloc[100]
sample_row
file_id WEBFire977 img_name WEBFire977.jpg xmax 428 ymax 389 xmin 376 ymin 335 width 1280 height 720 Name: 100, dtype: object
# select a random image and read it
sample_img = cv2.imread(f"{DATA_DIR}/images/{sample_row.img_name}")
# check shape for the image
sample_img.shape
(720, 1280, 3)
plt.imshow(sample_img, cmap='flare')
<matplotlib.image.AxesImage at 0x7f9c9f3bc510>
# select all records that have same file id as above
df[df['file_id'] == sample_row.file_id]
| file_id | img_name | xmax | ymax | xmin | ymin | width | height | |
|---|---|---|---|---|---|---|---|---|
| 100 | WEBFire977 | WEBFire977.jpg | 428 | 389 | 376 | 335 | 1280 | 720 |
| 101 | WEBFire977 | WEBFire977.jpg | 764 | 474 | 462 | 368 | 1280 | 720 |
| 102 | WEBFire977 | WEBFire977.jpg | 1173 | 495 | 791 | 387 | 1280 | 720 |
| 103 | WEBFire977 | WEBFire977.jpg | 1293 | 522 | 1211 | 460 | 1280 | 720 |
anot_img = sample_img.copy()
curr_record = df[df['file_id'] == sample_row.file_id].reset_index(drop=True)
for r in range(curr_record.shape[0]):
row = curr_record.iloc[r]
cv2.rectangle(anot_img, (row.xmin, row.ymin), (row.xmax, row.ymax), (255,0, 0),5)
# display the imahge
plt.figure(figsize = (12,12))
plt.imshow(anot_img)
<matplotlib.image.AxesImage at 0x7f9c9d69e5d0>
# create a function to do the above.
def Draw_bbox_on_image(img,file_id):
curr_record = df[df['file_id'] == file_id].reset_index(drop=True)
drawn_img = img.copy()
for r in range(curr_record.shape[0]):
row = curr_record.iloc[r]
cv2.rectangle(drawn_img, (row.xmin, row.ymin), (row.xmax, row.ymax), (255,0, 0),5)
return drawn_img
# test the function on a random id
img_1000 = cv2.imread(f"{DATA_DIR}/images/{df.iloc[1000].img_name}")
plt.figure(figsize=(12,12))
plt.imshow(Draw_bbox_on_image(img_1000, df.iloc[1000].file_id))
<matplotlib.image.AxesImage at 0x7f9c9d621810>
df[df.file_id == df.iloc[1000].file_id]
| file_id | img_name | xmax | ymax | xmin | ymin | width | height | |
|---|---|---|---|---|---|---|---|---|
| 1000 | 406 | 406.jpg | 585 | 407 | 189 | 157 | 800 | 598 |
df_copy = df.copy()
< object-class-ID> <X center> <Y center> <Box width> <Box height>
0 0.563462 0.686216 0.462500 0.195205
7 0.880769 0.796447 0.041346 0.112586
2 0.880769 0.796447 0.041346 0.112586
0 0.564663 0.679366 0.463942 0.181507
0 0.566106 0.658390 0.469712 0.192637
1 0.565144 0.359803 0.118750 0.107449
Each Value is sepearated by a space and For Information for each object is on Its new Line.
Since the annotations needs to be normalized, lets Normalize them and Extyract the Center and Dimension for Each Fire object.
df.columns
Index(['file_id', 'img_name', 'xmax', 'ymax', 'xmin', 'ymin', 'width',
'height'],
dtype='object')
# first, normalization of the bbox infromation to be between a range of 1 and 0.
#We divide by height or widht
df['x_min'] = df.apply(lambda record: (record.xmin)/record.width, axis =1)
df['y_min'] = df.apply(lambda record: (record.ymin)/record.height, axis =1)
df['x_max'] = df.apply(lambda record: (record.xmax)/record.width, axis =1)
df['y_max'] = df.apply(lambda record: (record.ymax)/record.height, axis =1)
# extract the Mid point location
df['x_mid'] = df.apply(lambda record: (record.x_max+record.x_min)/2, axis =1)
df['y_mid'] = df.apply(lambda record: (record.y_max+record.y_min)/2, axis =1)
# Extract the height and width of the object
df['w'] = df.apply(lambda record: (record.x_max-record.x_min), axis =1)
df['h'] = df.apply(lambda record: (record.y_max-record.y_min), axis =1)
df.sample()
| file_id | img_name | xmax | ymax | xmin | ymin | width | height | x_min | y_min | x_max | y_max | x_mid | y_mid | w | h | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 3853 | MirrorWEBSmoke2796 | MirrorWEBSmoke2796.jpg | 428 | 395 | 258 | 199 | 822 | 617 | 0.313869 | 0.322528 | 0.520681 | 0.640194 | 0.417275 | 0.481361 | 0.206813 | 0.317666 |
df['area'] = df['w']*df['h']
df.head()
| file_id | img_name | xmax | ymax | xmin | ymin | width | height | x_min | y_min | x_max | y_max | x_mid | y_mid | w | h | area | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | WEBSmoke1241 | WEBSmoke1241.jpg | 632 | 427 | 508 | 247 | 1086 | 652 | 0.467772 | 0.378834 | 0.581952 | 0.654908 | 0.524862 | 0.516871 | 0.114180 | 0.276074 | 0.031522 |
| 1 | WEBFire568 | WEBFire568.jpg | 891 | 576 | 3 | 214 | 1000 | 657 | 0.003000 | 0.325723 | 0.891000 | 0.876712 | 0.447000 | 0.601218 | 0.888000 | 0.550989 | 0.489279 |
| 2 | WEBFire568 | WEBFire568.jpg | 833 | 388 | 705 | 258 | 1000 | 657 | 0.705000 | 0.392694 | 0.833000 | 0.590563 | 0.769000 | 0.491629 | 0.128000 | 0.197869 | 0.025327 |
| 3 | WEBSmoke1654 | WEBSmoke1654.jpg | 998 | 583 | 704 | 109 | 960 | 640 | 0.733333 | 0.170313 | 1.039583 | 0.910937 | 0.886458 | 0.540625 | 0.306250 | 0.740625 | 0.226816 |
| 4 | WEBFire406 | WEBFire406.jpg | 889 | 522 | 439 | 298 | 1280 | 720 | 0.342969 | 0.413889 | 0.694531 | 0.725000 | 0.518750 | 0.569444 | 0.351563 | 0.311111 | 0.109375 |
# create a dataframe with n unique files
Since we have a dataframe and a single image can have more than one object, for easier labels creation, lets get all unique files with their objects together on the same record.
Information regarding the object are going to be inside a list i,e A list of Dictionarys Example for a single File:
[
{'x_min': 0.4677716390423573, 'y_min': 0.3788, "x_max":0.12435,"y_max":0.234352, "x_mid":0.8829343, "y_mid":0.23435, "w":0.23, "h":0.1234},
{.....},
{.....},
..........
]
# a list to hold all unique files information. It will help in easier convertsiopn to dataframe
TRAIN =[]
for img_id in tqdm(df['file_id'].unique()):
#get all rows that has the current id
curr_df = df[df['file_id'] ==img_id].reset_index(drop=True)
#get unique information
base_details = dict(curr_df.loc[0][['file_id','img_name', 'width', 'height']])
# a list to hold bbox annotation information
information =[]
#iterate through the whole records of the current id while extracting their annotation informations
for indx in range(curr_df.shape[0]):
#get their information as dic and add to the informatiuon list above
other_details = dict(curr_df.loc[indx][["x_min", "y_min","x_max","y_max", "x_mid", "y_mid", "w", "h", "area" ]])
information.append(other_details)
# append information for the current file
TRAIN.append([base_details['file_id'], base_details['img_name'],base_details['width'],base_details['height'],information])
0%| | 0/2187 [00:00<?, ?it/s]
# create a datafrmae from the above created list.
processed_df = pd.DataFrame(TRAIN, columns =['image_id', "img_name", "width", "height", "information"])
# how the current data looks.
processed_df
| image_id | img_name | width | height | information | |
|---|---|---|---|---|---|
| 0 | WEBSmoke1241 | WEBSmoke1241.jpg | 1086 | 652 | [{'x_min': 0.4677716390423573, 'y_min': 0.3788... |
| 1 | WEBFire568 | WEBFire568.jpg | 1000 | 657 | [{'x_min': 0.003, 'y_min': 0.3257229832572298,... |
| 2 | WEBSmoke1654 | WEBSmoke1654.jpg | 960 | 640 | [{'x_min': 0.7333333333333333, 'y_min': 0.1703... |
| 3 | WEBFire406 | WEBFire406.jpg | 1280 | 720 | [{'x_min': 0.34296875, 'y_min': 0.413888888888... |
| 4 | WEBFire547 | WEBFire547.jpg | 1920 | 1080 | [{'x_min': 0.4505208333333333, 'y_min': 0.6435... |
| ... | ... | ... | ... | ... | ... |
| 2182 | new_fire_63 | new_fire_63.jpg | 400 | 300 | [{'x_min': 0.4425, 'y_min': 0.2433333333333333... |
| 2183 | new_fire_53 | new_fire_53.jpg | 960 | 640 | [{'x_min': 0.378125, 'y_min': 0.4390625, 'x_ma... |
| 2184 | new_fire_68 | new_fire_68.jpg | 740 | 388 | [{'x_min': 0.6959459459459459, 'y_min': 0.5824... |
| 2185 | new_fire_58 | new_fire_58.jpg | 640 | 360 | [{'x_min': 0.4109375, 'y_min': 0.5416666666666... |
| 2186 | new_fire_61 | new_fire_61.jpg | 1200 | 900 | [{'x_min': 0.7791666666666667, 'y_min': 0.0033... |
2187 rows × 5 columns
# split into training and validation
gkf = GroupKFold(n_splits = 10)
processed_df['fold'] = -1
for fold, (train_idx, val_idx) in enumerate(gkf.split(processed_df, groups = processed_df.image_id.tolist())):
processed_df.loc[val_idx, 'fold'] = fold
processed_df.head()
| image_id | img_name | width | height | information | fold | |
|---|---|---|---|---|---|---|
| 0 | WEBSmoke1241 | WEBSmoke1241.jpg | 1086 | 652 | [{'x_min': 0.4677716390423573, 'y_min': 0.3788... | 1 |
| 1 | WEBFire568 | WEBFire568.jpg | 1000 | 657 | [{'x_min': 0.003, 'y_min': 0.3257229832572298,... | 8 |
| 2 | WEBSmoke1654 | WEBSmoke1654.jpg | 960 | 640 | [{'x_min': 0.7333333333333333, 'y_min': 0.1703... | 0 |
| 3 | WEBFire406 | WEBFire406.jpg | 1280 | 720 | [{'x_min': 0.34296875, 'y_min': 0.413888888888... | 4 |
| 4 | WEBFire547 | WEBFire547.jpg | 1920 | 1080 | [{'x_min': 0.4505208333333333, 'y_min': 0.6435... | 6 |
processed_df['fold'].value_counts(normalize =True)
1 0.100137 0 0.100137 4 0.100137 6 0.100137 2 0.100137 5 0.100137 3 0.100137 8 0.099680 7 0.099680 9 0.099680 Name: fold, dtype: float64
fold
9
# get all image ids for both training and validation with the bbox
train_fold_files_ids = []
val_fold_files_ids = []
val_fold_files_ids += list(processed_df[processed_df.fold==fold].image_id.unique())
train_fold_files_ids += list(processed_df[processed_df.fold!=fold].image_id.unique())
len(train_fold_files_ids), len(val_fold_files_ids)
(1969, 218)
# check the directory
!pwd
/content
├── data.yaml
base_dir:
├── images
│ ├── train
│ └── validation
└── labels
├── train
└── validation
if you have test, it might look as follows;
├── data.yaml
├── test
│ ├── images
│ └── labels
├── train
│ ├── images
│ └── labels
└── valid
├── images
└── labels
lets Create the above folder structure so as to start transferring data into them.
# create thr directorues as follows
# base_dir
# images
# train (contains image files)
# validation (contains image files)
# labels
# train (contains .txt files)
# validation (contains .txt files)
os.makedirs(f'{DATA_DIR}/yolo/labels/train', exist_ok = True)
os.makedirs(f'{DATA_DIR}/yolo/labels/val', exist_ok = True)
os.makedirs(f'{DATA_DIR}/yolo/images/train', exist_ok = True)
os.makedirs(f'{DATA_DIR}/yolo/images/val', exist_ok = True)
sample_d = processed_df[processed_df['image_id']== train_fold_files_ids[0]]
sample_d
| image_id | img_name | width | height | information | fold | |
|---|---|---|---|---|---|---|
| 0 | WEBSmoke1241 | WEBSmoke1241.jpg | 1086 | 652 | [{'x_min': 0.4677716390423573, 'y_min': 0.3788... | 1 |
class x-center y-center width height
Below is the Implimentation of the above
YOLO_IMGS_DIR = "/content/drive/MyDrive/FIRE/yolo/images/"
YOLO_LBL_DIR = "/content/drive/MyDrive/FIRE/yolo/labels/"
IMG_DIRS = "/content/drive/MyDrive/FIRE/images"
for xq in sample_d['information'].values[0]:
print(0, xq['x_mid'], xq['y_mid'], xq['w'] , xq['h'])
0 0.5248618784530387 0.5168711656441718 0.11418047882136273 0.27607361963190186
"""
In this cell, It is a function that iterates through each row in the df
It first determine whether the image belows to training or testing sets.
For each image:
1- get the info for each bounding box
2- write the bounding box info to a txt file
3- save the txt file in the correct folder
4- copy the image to the correct folder
Before saving the image, it must be processed by applying clahe function/
class, center (x,y), width, height
Also the format for YOLO dataset is followed i.e
"""
def process_data_for_yolo(df, file_id_lists, data_type='train'):
"""
Reads details for an image and transfers them to their respective folders when proceesed.
"""
#iterate through each row
#for _, row in notebook.tqdm(df.iterrows(), total=len(df)):
for each_id in tqdm(file_id_lists, total=len(file_id_lists)):
#print(each_id, file_id_lists)
row = df.loc[each_id]
#get img information
file_id = row['image_id']
file_name = row['img_name']
# Convert into the Yolo input format
yolo_data = []
for xq in row['information']:
curr_bbox_infor = [0, xq['x_mid'], xq['y_mid'], xq['w'] , xq['h']]
if xq['x_mid']<=0 and xq['y_mid']<=0 and xq['w']<=0 and xq['h']<=0:
pass
else:
yolo_data.append(curr_bbox_infor)
# convert to nump array
yolo_data = np.array(yolo_data)
#print(yolo_data)
#copy image to another directory where training will occur
full_file_path = f"{IMG_DIRS}/{file_name}"
shutil.copy(full_file_path, f'{YOLO_IMGS_DIR}{data_type}')
#saved format must be class, center (x,y), width, heihgt
np.savetxt(os.path.join(f"{YOLO_LBL_DIR}/{data_type}/{file_id}.txt"),
yolo_data,
fmt=["%d", "%f", "%f", "%f", "%f"]
)
# since we using Id to create the data, lets set index as file id.
indexed_train = processed_df.copy()
indexed_train.index = processed_df['image_id']
# process training
process_data_for_yolo(indexed_train, train_fold_files_ids, 'train')
# process testing
process_data_for_yolo(indexed_train, val_fold_files_ids, 'val')
0%| | 0/1969 [00:00<?, ?it/s]
0%| | 0/218 [00:00<?, ?it/s]
# check the size of trainig
len(glob(f"{YOLO_IMGS_DIR}/train/*")), len(glob(f"{YOLO_LBL_DIR}/train/*"))
(1969, 1969)
# size of validation images
len(glob(f"{YOLO_IMGS_DIR}/val/*")), len(glob(f"{YOLO_LBL_DIR}/val/*"))
(218, 218)
# change directory to where the model for yolo will be stored.
os.chdir("/content/drive/MyDrive/FIRE/yolo/")
# print current wrking directory
!pwd
/content/drive/MyDrive/FIRE/yolo
There are 3 config files types present in YAML format. When the repo (Ultralyric) is cloned all of these are download. We are going to only customize one of them whihc will contain information about our training dataset. These config types include;
The Data Config File- Describes the dataset to be used. It contains information such as;
The Model Config File - Shows the model Architecture. Ultralytics supports several YOLOv5 architectures, named P5 models, which varies mainly by their parameters size. They Include
YOLOv5x as out initial weights.large, medium and low: We are going to user default hyperparameters hence no need to edit them.# save the data (labels and images directories into a txt file)
with open(os.path.join( "/content/drive/MyDrive/FIRE/yolo/" , 'train.txt'), 'w') as f:
for path in glob('/content/drive/MyDrive/FIRE/yolo/images/train/*'):
f.write(path+'\n')
with open(os.path.join( "/content/drive/MyDrive/FIRE/yolo/" , 'val.txt'), 'w') as f:
for path in glob("/content/drive/MyDrive/FIRE/yolo/images/val/*"):
f.write(path+'\n')
# example of files stored
open(os.path.join( "/content/drive/MyDrive/FIRE/yolo/" , 'val.txt'), 'r+').read().split("\n")[:10]
['/content/drive/MyDrive/FIRE/yolo/images/val/WEBFire550.jpg', '/content/drive/MyDrive/FIRE/yolo/images/val/WEBFire954.jpg', '/content/drive/MyDrive/FIRE/yolo/images/val/WEBFire2047.jpg', '/content/drive/MyDrive/FIRE/yolo/images/val/WEBFire1909.jpg', '/content/drive/MyDrive/FIRE/yolo/images/val/WEBFire2056.jpg', '/content/drive/MyDrive/FIRE/yolo/images/val/WEBFire595.jpg', '/content/drive/MyDrive/FIRE/yolo/images/val/WEBFire324.jpg', '/content/drive/MyDrive/FIRE/yolo/images/val/WEBFire360.jpg', '/content/drive/MyDrive/FIRE/yolo/images/val/WEBFire312.jpg', '/content/drive/MyDrive/FIRE/yolo/images/val/WEBFire537.jpg']
'train': <path to train data>,
'val': <path to val data>,
'nc': 5,
'names': ['label0', 'label1', 'label2', 'label3', 'label4']}
# information to be used as daata by yolo
yolo_data = dict(
train = os.path.join( "/content/drive/MyDrive/FIRE/yolo/" , 'train.txt') ,
val = os.path.join( "/content/drive/MyDrive/FIRE/yolo/", 'val.txt' ),
nc = 1,# there is only one class
names = ["Fire"]
)
yolo_data
{'train': '/content/drive/MyDrive/FIRE/yolo/train.txt',
'val': '/content/drive/MyDrive/FIRE/yolo/val.txt',
'nc': 1,
'names': ['Fire']}
# save the file as yaml with the information
import yaml
with open(os.path.join( "/content/drive/MyDrive/FIRE/yolo/" , 'fire.yaml'), 'w') as outfile:
yaml.dump(yolo_data, outfile, default_flow_style=False)
# recheck
filler = open(os.path.join("/content/drive/MyDrive/FIRE/yolo/" , 'fire.yaml'), 'r')
print(filler.read())
names: - Fire nc: 1 train: /content/drive/MyDrive/FIRE/yolo/train.txt val: /content/drive/MyDrive/FIRE/yolo/val.txt
# """"
# clone yolo repor
!git clone https://github.com/ultralytics/yolov5.git
Cloning into 'yolov5'... remote: Enumerating objects: 14468, done. remote: Counting objects: 100% (22/22), done. remote: Compressing objects: 100% (18/18), done. remote: Total 14468 (delta 7), reused 10 (delta 4), pack-reused 14446 Receiving objects: 100% (14468/14468), 13.46 MiB | 8.57 MiB/s, done. Resolving deltas: 100% (9980/9980), done.
!pwd
/content/drive/MyDrive/FIRE/yolo
# move to the directory with downloaded code
%cd /content/drive/MyDrive/FIRE/yolo/yolov5
/content/drive/MyDrive/FIRE/yolo/yolov5
# install the requirements.txt
%pip install -qr requirements.txt
|████████████████████████████████| 1.6 MB 44.1 MB/s eta 0:00:01
import torch
print('Torch -v %s %s' % (torch.__version__, torch.cuda.get_device_properties(0) if torch.cuda.is_available() else 'CPU'))
Torch -v 1.12.1+cu113 _CudaDeviceProperties(name='Tesla T4', major=7, minor=5, total_memory=15109MB, multi_processor_count=40)
# login to wandb.
!pip install wandb -qq
import wandb
|████████████████████████████████| 1.9 MB 30.3 MB/s
|████████████████████████████████| 182 kB 71.5 MB/s
|████████████████████████████████| 166 kB 68.3 MB/s
|████████████████████████████████| 63 kB 1.6 MB/s
|████████████████████████████████| 166 kB 66.7 MB/s
|████████████████████████████████| 162 kB 65.3 MB/s
|████████████████████████████████| 162 kB 81.3 MB/s
|████████████████████████████████| 158 kB 77.9 MB/s
|████████████████████████████████| 157 kB 79.0 MB/s
|████████████████████████████████| 157 kB 77.8 MB/s
|████████████████████████████████| 157 kB 72.8 MB/s
|████████████████████████████████| 157 kB 79.9 MB/s
|████████████████████████████████| 157 kB 77.3 MB/s
|████████████████████████████████| 157 kB 76.0 MB/s
|████████████████████████████████| 157 kB 74.1 MB/s
|████████████████████████████████| 156 kB 80.4 MB/s
Building wheel for pathtools (setup.py) ... done
# login
wandb.login()
wandb: Logging into wandb.ai. (Learn how to deploy a W&B server locally: https://wandb.me/wandb-server) wandb: You can find your API key in your browser here: https://wandb.ai/authorize wandb: Paste an API key from your profile and hit enter, or press ctrl+c to quit:
··········
wandb: Appending key for api.wandb.ai to your netrc file: /root/.netrc
True
# project name
wandb.init(project="DevFest")
wandb: Currently logged in as: stephenkamau. Use `wandb login --relogin` to force relogin
/content/drive/MyDrive/FIRE/yolo/yolov5/wandb/run-20221104_191012-16pdmx1p
What some of the parameters passed and what are they used for?:
1. --weights => the pre-trained model that we are using.
The list of available pre-trained models can be found here:
https://github.com/ultralytics/yolov5
2. --save-txt => The predicted bbox coordinates get saved to a txt file. One txt file per image.
3. --save-conf => The conf score gets included in the above txt file.
4. --img => The image will be resized to this size before creating the mosaic.
5. --conf => The confidence threshold
6. --rect => Means don't use mosaic augmentation during training
7. --name => Give a model a name e.g. --name my_model
8. --batch => batch size
9. --epochs => number of training epochs
10. --data => the yaml file path
11. --exist-ok => do not increment the project names with each run i.e. don't change exp to epx2, exp3 etc.
12. --nosave => do not save the images/videos (helpful when deploying to a server) etc
detect.py, train.py and val.py to investigate how they are used and many otheres.# !WANDB_MODE="dryrun" not to use wandb
!WANDB_MODE="online" python train.py --exist-ok --img 640 --batch 16 --epochs 30 --data /content/drive/MyDrive/FIRE/yolo/fire.yaml --weights yolov5x.pt
wandb: Currently logged in as: stephenkamau. Use `wandb login --relogin` to force relogin train: weights=yolov5x.pt, cfg=, data=/content/drive/MyDrive/FIRE/yolo/fire.yaml, hyp=data/hyps/hyp.scratch-low.yaml, epochs=30, batch_size=16, imgsz=640, rect=False, resume=False, nosave=False, noval=False, noautoanchor=False, noplots=False, evolve=None, bucket=, cache=None, image_weights=False, device=, multi_scale=False, single_cls=False, optimizer=SGD, sync_bn=False, workers=8, project=runs/train, name=exp, exist_ok=True, quad=False, cos_lr=False, label_smoothing=0.0, patience=100, freeze=[0], save_period=-1, seed=0, local_rank=-1, entity=None, upload_dataset=False, bbox_interval=-1, artifact_alias=latest github: up to date with https://github.com/ultralytics/yolov5 ✅ YOLOv5 🚀 v6.2-226-gfde7758 Python-3.7.15 torch-1.12.1+cu113 CUDA:0 (Tesla T4, 15110MiB) hyperparameters: lr0=0.01, lrf=0.01, momentum=0.937, weight_decay=0.0005, warmup_epochs=3.0, warmup_momentum=0.8, warmup_bias_lr=0.1, box=0.05, cls=0.5, cls_pw=1.0, obj=1.0, obj_pw=1.0, iou_t=0.2, anchor_t=4.0, fl_gamma=0.0, hsv_h=0.015, hsv_s=0.7, hsv_v=0.4, degrees=0.0, translate=0.1, scale=0.5, shear=0.0, perspective=0.0, flipud=0.0, fliplr=0.5, mosaic=1.0, mixup=0.0, copy_paste=0.0 ClearML: run 'pip install clearml' to automatically track, visualize and remotely train YOLOv5 🚀 in ClearML Comet: run 'pip install comet_ml' to automatically track and visualize YOLOv5 🚀 runs in Comet TensorBoard: Start with 'tensorboard --logdir runs/train', view at http://localhost:6006/ wandb: Tracking run with wandb version 0.13.5 wandb: Run data is saved locally in /content/drive/MyDrive/FIRE/yolo/yolov5/wandb/run-20221104_191111-5cnebn97 wandb: Run `wandb offline` to turn off syncing. wandb: Syncing run stilted-water-16 wandb: ⭐️ View project at https://wandb.ai/stephenkamau/YOLOv5 wandb: 🚀 View run at https://wandb.ai/stephenkamau/YOLOv5/runs/5cnebn97 Downloading https://ultralytics.com/assets/Arial.ttf to /root/.config/Ultralytics/Arial.ttf... 100% 755k/755k [00:00<00:00, 95.0MB/s] Downloading https://github.com/ultralytics/yolov5/releases/download/v6.2/yolov5x.pt to yolov5x.pt... 100% 166M/166M [00:35<00:00, 4.90MB/s] Overriding model.yaml nc=80 with nc=1 from n params module arguments 0 -1 1 8800 models.common.Conv [3, 80, 6, 2, 2] 1 -1 1 115520 models.common.Conv [80, 160, 3, 2] 2 -1 4 309120 models.common.C3 [160, 160, 4] 3 -1 1 461440 models.common.Conv [160, 320, 3, 2] 4 -1 8 2259200 models.common.C3 [320, 320, 8] 5 -1 1 1844480 models.common.Conv [320, 640, 3, 2] 6 -1 12 13125120 models.common.C3 [640, 640, 12] 7 -1 1 7375360 models.common.Conv [640, 1280, 3, 2] 8 -1 4 19676160 models.common.C3 [1280, 1280, 4] 9 -1 1 4099840 models.common.SPPF [1280, 1280, 5] 10 -1 1 820480 models.common.Conv [1280, 640, 1, 1] 11 -1 1 0 torch.nn.modules.upsampling.Upsample [None, 2, 'nearest'] 12 [-1, 6] 1 0 models.common.Concat [1] 13 -1 4 5332480 models.common.C3 [1280, 640, 4, False] 14 -1 1 205440 models.common.Conv [640, 320, 1, 1] 15 -1 1 0 torch.nn.modules.upsampling.Upsample [None, 2, 'nearest'] 16 [-1, 4] 1 0 models.common.Concat [1] 17 -1 4 1335040 models.common.C3 [640, 320, 4, False] 18 -1 1 922240 models.common.Conv [320, 320, 3, 2] 19 [-1, 14] 1 0 models.common.Concat [1] 20 -1 4 4922880 models.common.C3 [640, 640, 4, False] 21 -1 1 3687680 models.common.Conv [640, 640, 3, 2] 22 [-1, 10] 1 0 models.common.Concat [1] 23 -1 4 19676160 models.common.C3 [1280, 1280, 4, False] 24 [17, 20, 23] 1 40374 models.yolo.Detect [1, [[10, 13, 16, 30, 33, 23], [30, 61, 62, 45, 59, 119], [116, 90, 156, 198, 373, 326]], [320, 640, 1280]] Model summary: 445 layers, 86217814 parameters, 86217814 gradients, 204.6 GFLOPs Transferred 739/745 items from yolov5x.pt AMP: checks passed ✅ optimizer: SGD(lr=0.01) with parameter groups 123 weight(decay=0.0), 126 weight(decay=0.0005), 126 bias albumentations: Blur(p=0.01, blur_limit=(3, 7)), MedianBlur(p=0.01, blur_limit=(3, 7)), ToGray(p=0.01), CLAHE(p=0.01, clip_limit=(1, 4.0), tile_grid_size=(8, 8)) train: Scanning '/content/drive/MyDrive/FIRE/yolo/train' images and labels...1969 found, 0 missing, 0 empty, 63 corrupt: 100% 1969/1969 [00:07<00:00, 272.41it/s] train: WARNING ⚠️ /content/drive/MyDrive/FIRE/yolo/images/train/1096.jpg: ignoring corrupt image/label: non-normalized or out of bounds coordinates [ 1.0667] train: WARNING ⚠️ /content/drive/MyDrive/FIRE/yolo/images/train/1126.jpg: ignoring corrupt image/label: non-normalized or out of bounds coordinates [ 1.1694 1.1548] train: WARNING ⚠️ /content/drive/MyDrive/FIRE/yolo/images/train/1287.jpg: ignoring corrupt image/label: non-normalized or out of bounds coordinates [ 1.1704] train: WARNING ⚠️ /content/drive/MyDrive/FIRE/yolo/images/train/352.jpg: ignoring corrupt image/label: non-normalized or out of bounds coordinates [ 1.1806] train: WARNING ⚠️ /content/drive/MyDrive/FIRE/yolo/images/train/475.jpg: ignoring corrupt image/label: non-normalized or out of bounds coordinates [ 1.2024] train: WARNING ⚠️ /content/drive/MyDrive/FIRE/yolo/images/train/591.jpg: ignoring corrupt image/label: non-normalized or out of bounds coordinates [ 1.3124] train: WARNING ⚠️ /content/drive/MyDrive/FIRE/yolo/images/train/664.jpg: ignoring corrupt image/label: non-normalized or out of bounds coordinates [ 1.2403] train: WARNING ⚠️ /content/drive/MyDrive/FIRE/yolo/images/train/930.jpg: ignoring corrupt image/label: non-normalized or out of bounds coordinates [ 1.154] train: WARNING ⚠️ /content/drive/MyDrive/FIRE/yolo/images/train/FireDetectionImage_MirrorWEBFire089.jpg: ignoring corrupt image/label: non-normalized or out of bounds coordinates [ 1.0396] train: WARNING ⚠️ /content/drive/MyDrive/FIRE/yolo/images/train/FireDetectionImage_NoiseWEBFire088.jpg: ignoring corrupt image/label: non-normalized or out of bounds coordinates [ 1.1009 1.2049] train: WARNING ⚠️ /content/drive/MyDrive/FIRE/yolo/images/train/FireDetectionImage_NoiseWEBFire089.jpg: ignoring corrupt image/label: non-normalized or out of bounds coordinates [ 1.0396] train: WARNING ⚠️ /content/drive/MyDrive/FIRE/yolo/images/train/FireDetectionImage_WEBFire089.jpg: ignoring corrupt image/label: non-normalized or out of bounds coordinates [ 1.0396] train: WARNING ⚠️ /content/drive/MyDrive/FIRE/yolo/images/train/MirrorWEBFire1304.jpg: ignoring corrupt image/label: non-normalized or out of bounds coordinates [ 1.1489] train: WARNING ⚠️ /content/drive/MyDrive/FIRE/yolo/images/train/MirrorWEBFire1370.jpg: ignoring corrupt image/label: non-normalized or out of bounds coordinates [ 1.11] train: WARNING ⚠️ /content/drive/MyDrive/FIRE/yolo/images/train/MirrorWEBFire1371.jpg: ignoring corrupt image/label: non-normalized or out of bounds coordinates [ 1.09] train: WARNING ⚠️ /content/drive/MyDrive/FIRE/yolo/images/train/MirrorWEBFire1422.jpg: ignoring corrupt image/label: non-normalized or out of bounds coordinates [ 1.1939] train: WARNING ⚠️ /content/drive/MyDrive/FIRE/yolo/images/train/MirrorWEBFire1429.jpg: ignoring corrupt image/label: non-normalized or out of bounds coordinates [ 1.0888] train: WARNING ⚠️ /content/drive/MyDrive/FIRE/yolo/images/train/MirrorWEBFire1482.jpg: ignoring corrupt image/label: non-normalized or out of bounds coordinates [ 1.1694] train: WARNING ⚠️ /content/drive/MyDrive/FIRE/yolo/images/train/MirrorWEBSmoke1315.jpg: ignoring corrupt image/label: non-normalized or out of bounds coordinates [ 1.0151] train: WARNING ⚠️ /content/drive/MyDrive/FIRE/yolo/images/train/MirrorWEBSmoke1334.jpg: ignoring corrupt image/label: non-normalized or out of bounds coordinates [ 1.0665] train: WARNING ⚠️ /content/drive/MyDrive/FIRE/yolo/images/train/NoiseWEBFire055.jpg: ignoring corrupt image/label: non-normalized or out of bounds coordinates [ 1.035] train: WARNING ⚠️ /content/drive/MyDrive/FIRE/yolo/images/train/NoiseWEBFire1064.jpg: ignoring corrupt image/label: non-normalized or out of bounds coordinates [ 1.1781] train: WARNING ⚠️ /content/drive/MyDrive/FIRE/yolo/images/train/NoiseWEBFire1083.jpg: ignoring corrupt image/label: non-normalized or out of bounds coordinates [ 1.0047] train: WARNING ⚠️ /content/drive/MyDrive/FIRE/yolo/images/train/NoiseWEBFire1086.jpg: ignoring corrupt image/label: non-normalized or out of bounds coordinates [ 1.05] train: WARNING ⚠️ /content/drive/MyDrive/FIRE/yolo/images/train/NoiseWEBFire1100.jpg: ignoring corrupt image/label: non-normalized or out of bounds coordinates [ 1.1156] train: WARNING ⚠️ /content/drive/MyDrive/FIRE/yolo/images/train/NoiseWEBFire1107.jpg: ignoring corrupt image/label: non-normalized or out of bounds coordinates [ 1.1078] train: WARNING ⚠️ /content/drive/MyDrive/FIRE/yolo/images/train/NoiseWEBFire1305.jpg: ignoring corrupt image/label: non-normalized or out of bounds coordinates [ 1.1528 1.0056] train: WARNING ⚠️ /content/drive/MyDrive/FIRE/yolo/images/train/NoiseWEBFire1372.jpg: ignoring corrupt image/label: non-normalized or out of bounds coordinates [ 1.2113] train: WARNING ⚠️ /content/drive/MyDrive/FIRE/yolo/images/train/NoiseWEBFire1401.jpg: ignoring corrupt image/label: non-normalized or out of bounds coordinates [ 1.0626] train: WARNING ⚠️ /content/drive/MyDrive/FIRE/yolo/images/train/NoiseWEBFire1424.jpg: ignoring corrupt image/label: non-normalized or out of bounds coordinates [ 1.1621] train: WARNING ⚠️ /content/drive/MyDrive/FIRE/yolo/images/train/NoiseWEBFire1430.jpg: ignoring corrupt image/label: non-normalized or out of bounds coordinates [ 1.0255] train: WARNING ⚠️ /content/drive/MyDrive/FIRE/yolo/images/train/WEBFire055.jpg: ignoring corrupt image/label: non-normalized or out of bounds coordinates [ 1.035] train: WARNING ⚠️ /content/drive/MyDrive/FIRE/yolo/images/train/WEBFire1064.jpg: ignoring corrupt image/label: non-normalized or out of bounds coordinates [ 1.1781] train: WARNING ⚠️ /content/drive/MyDrive/FIRE/yolo/images/train/WEBFire1083.jpg: ignoring corrupt image/label: non-normalized or out of bounds coordinates [ 1.0047] train: WARNING ⚠️ /content/drive/MyDrive/FIRE/yolo/images/train/WEBFire1085.jpg: ignoring corrupt image/label: non-normalized or out of bounds coordinates [ 1.0281] train: WARNING ⚠️ /content/drive/MyDrive/FIRE/yolo/images/train/WEBFire1086.jpg: ignoring corrupt image/label: non-normalized or out of bounds coordinates [ 1.05] train: WARNING ⚠️ /content/drive/MyDrive/FIRE/yolo/images/train/WEBFire1100.jpg: ignoring corrupt image/label: non-normalized or out of bounds coordinates [ 1.1156] train: WARNING ⚠️ /content/drive/MyDrive/FIRE/yolo/images/train/WEBFire1107.jpg: ignoring corrupt image/label: non-normalized or out of bounds coordinates [ 1.1078] train: WARNING ⚠️ /content/drive/MyDrive/FIRE/yolo/images/train/WEBFire1113.jpg: ignoring corrupt image/label: non-normalized or out of bounds coordinates [ 1.1453] train: WARNING ⚠️ /content/drive/MyDrive/FIRE/yolo/images/train/WEBFire1114.jpg: ignoring corrupt image/label: non-normalized or out of bounds coordinates [ 1.1531] train: WARNING ⚠️ /content/drive/MyDrive/FIRE/yolo/images/train/WEBFire1304.jpg: ignoring corrupt image/label: non-normalized or out of bounds coordinates [ 1.1489] train: WARNING ⚠️ /content/drive/MyDrive/FIRE/yolo/images/train/WEBFire1305.jpg: ignoring corrupt image/label: non-normalized or out of bounds coordinates [ 1.1528 1.0056] train: WARNING ⚠️ /content/drive/MyDrive/FIRE/yolo/images/train/WEBFire1372.jpg: ignoring corrupt image/label: non-normalized or out of bounds coordinates [ 1.2113] train: WARNING ⚠️ /content/drive/MyDrive/FIRE/yolo/images/train/WEBFire1401.jpg: ignoring corrupt image/label: non-normalized or out of bounds coordinates [ 1.0626] train: WARNING ⚠️ /content/drive/MyDrive/FIRE/yolo/images/train/WEBFire1424.jpg: ignoring corrupt image/label: non-normalized or out of bounds coordinates [ 1.1621] train: WARNING ⚠️ /content/drive/MyDrive/FIRE/yolo/images/train/WEBFire1430.jpg: ignoring corrupt image/label: non-normalized or out of bounds coordinates [ 1.0255] train: WARNING ⚠️ /content/drive/MyDrive/FIRE/yolo/images/train/WEBFire1498.jpg: ignoring corrupt image/label: non-normalized or out of bounds coordinates [ 1.0468] train: WARNING ⚠️ /content/drive/MyDrive/FIRE/yolo/images/train/WEBFire1547.jpg: ignoring corrupt image/label: non-normalized or out of bounds coordinates [ 1.2028] train: WARNING ⚠️ /content/drive/MyDrive/FIRE/yolo/images/train/WEBFire1733.jpg: ignoring corrupt image/label: non-normalized or out of bounds coordinates [ 1.0065] train: WARNING ⚠️ /content/drive/MyDrive/FIRE/yolo/images/train/WEBFire1807.jpg: ignoring corrupt image/label: non-normalized or out of bounds coordinates [ 1.06] train: WARNING ⚠️ /content/drive/MyDrive/FIRE/yolo/images/train/WEBFire1905.jpg: ignoring corrupt image/label: non-normalized or out of bounds coordinates [ 1.2385] train: WARNING ⚠️ /content/drive/MyDrive/FIRE/yolo/images/train/WEBFire1906.jpg: ignoring corrupt image/label: non-normalized or out of bounds coordinates [ 1.3026] train: WARNING ⚠️ /content/drive/MyDrive/FIRE/yolo/images/train/WEBFire1907.jpg: ignoring corrupt image/label: non-normalized or out of bounds coordinates [ 1.2987 1.0033] train: WARNING ⚠️ /content/drive/MyDrive/FIRE/yolo/images/train/WEBFire2023.jpg: ignoring corrupt image/label: non-normalized or out of bounds coordinates [ 1.0157] train: WARNING ⚠️ /content/drive/MyDrive/FIRE/yolo/images/train/WEBFire559.jpg: ignoring corrupt image/label: non-normalized or out of bounds coordinates [ 1.063] train: WARNING ⚠️ /content/drive/MyDrive/FIRE/yolo/images/train/WEBFire942.jpg: ignoring corrupt image/label: non-normalized or out of bounds coordinates [ 1.0672] train: WARNING ⚠️ /content/drive/MyDrive/FIRE/yolo/images/train/WEBSmoke1082.jpg: ignoring corrupt image/label: non-normalized or out of bounds coordinates [ 1.0469] train: WARNING ⚠️ /content/drive/MyDrive/FIRE/yolo/images/train/WEBSmoke2380.jpg: ignoring corrupt image/label: non-normalized or out of bounds coordinates [ 1.0109] train: WARNING ⚠️ /content/drive/MyDrive/FIRE/yolo/images/train/f30a02ce7bfb2a23.jpg: ignoring corrupt image/label: non-normalized or out of bounds coordinates [ 1.0365] train: WARNING ⚠️ /content/drive/MyDrive/FIRE/yolo/images/train/ff64bd069a687687.jpg: ignoring corrupt image/label: non-normalized or out of bounds coordinates [ 1.3242] train: WARNING ⚠️ /content/drive/MyDrive/FIRE/yolo/images/train/new_fire_102.jpg: ignoring corrupt image/label: non-normalized or out of bounds coordinates [ 1.03] train: WARNING ⚠️ /content/drive/MyDrive/FIRE/yolo/images/train/new_fire_106.jpg: ignoring corrupt image/label: non-normalized or out of bounds coordinates [ 1.2672] train: WARNING ⚠️ /content/drive/MyDrive/FIRE/yolo/images/train/new_fire_77.jpg: ignoring corrupt image/label: non-normalized or out of bounds coordinates [ 1.0203] train: New cache created: /content/drive/MyDrive/FIRE/yolo/train.cache val: Scanning '/content/drive/MyDrive/FIRE/yolo/val' images and labels...218 found, 0 missing, 0 empty, 3 corrupt: 100% 218/218 [00:01<00:00, 180.79it/s] val: WARNING ⚠️ /content/drive/MyDrive/FIRE/yolo/images/val/347.jpg: ignoring corrupt image/label: non-normalized or out of bounds coordinates [ 1.0087] val: WARNING ⚠️ /content/drive/MyDrive/FIRE/yolo/images/val/776.jpg: ignoring corrupt image/label: non-normalized or out of bounds coordinates [ 1.136] val: WARNING ⚠️ /content/drive/MyDrive/FIRE/yolo/images/val/MirrorWEBFire1305.jpg: ignoring corrupt image/label: non-normalized or out of bounds coordinates [ 1.1528 1.0056] val: New cache created: /content/drive/MyDrive/FIRE/yolo/val.cache AutoAnchor: 4.83 anchors/target, 1.000 Best Possible Recall (BPR). Current anchors are a good fit to dataset ✅ Plotting labels to runs/train/exp/labels.jpg... Image sizes 640 train, 640 val Using 2 dataloader workers Logging results to runs/train/exp Starting training for 30 epochs... Epoch GPU_mem box_loss obj_loss cls_loss Instances Size 0/29 13.8G 0.08972 0.03707 0 4 640: 100% 120/120 [02:38<00:00, 1.32s/it] Class Images Instances P R mAP50 mAP50-95: 100% 7/7 [00:07<00:00, 1.08s/it] all 215 429 0.312 0.392 0.259 0.0967 Epoch GPU_mem box_loss obj_loss cls_loss Instances Size 1/29 13.9G 0.06739 0.02996 0 13 640: 100% 120/120 [02:36<00:00, 1.30s/it] Class Images Instances P R mAP50 mAP50-95: 100% 7/7 [00:06<00:00, 1.12it/s] all 215 429 0.38 0.504 0.406 0.16 Epoch GPU_mem box_loss obj_loss cls_loss Instances Size 2/29 13.9G 0.06109 0.02642 0 9 640: 100% 120/120 [02:37<00:00, 1.31s/it] Class Images Instances P R mAP50 mAP50-95: 100% 7/7 [00:07<00:00, 1.13s/it] all 215 429 0.534 0.561 0.518 0.21 Epoch GPU_mem box_loss obj_loss cls_loss Instances Size 3/29 13.9G 0.05512 0.02626 0 10 640: 100% 120/120 [02:37<00:00, 1.31s/it] Class Images Instances P R mAP50 mAP50-95: 100% 7/7 [00:06<00:00, 1.16it/s] all 215 429 0.51 0.541 0.481 0.198 Epoch GPU_mem box_loss obj_loss cls_loss Instances Size 4/29 13.9G 0.05099 0.02531 0 4 640: 100% 120/120 [02:30<00:00, 1.26s/it] Class Images Instances P R mAP50 mAP50-95: 100% 7/7 [00:06<00:00, 1.12it/s] all 215 429 0.662 0.522 0.615 0.285 Epoch GPU_mem box_loss obj_loss cls_loss Instances Size 5/29 13.9G 0.04949 0.02569 0 11 640: 100% 120/120 [02:36<00:00, 1.30s/it] Class Images Instances P R mAP50 mAP50-95: 100% 7/7 [00:06<00:00, 1.01it/s] all 215 429 0.598 0.585 0.591 0.261 Epoch GPU_mem box_loss obj_loss cls_loss Instances Size 6/29 13.9G 0.04703 0.02374 0 13 640: 100% 120/120 [02:32<00:00, 1.27s/it] Class Images Instances P R mAP50 mAP50-95: 100% 7/7 [00:05<00:00, 1.21it/s] all 215 429 0.711 0.634 0.656 0.308 Epoch GPU_mem box_loss obj_loss cls_loss Instances Size 7/29 13.9G 0.04585 0.02501 0 13 640: 100% 120/120 [02:40<00:00, 1.34s/it] Class Images Instances P R mAP50 mAP50-95: 100% 7/7 [00:06<00:00, 1.13it/s] all 215 429 0.605 0.664 0.633 0.28 Epoch GPU_mem box_loss obj_loss cls_loss Instances Size 8/29 13.9G 0.0444 0.02378 0 10 640: 100% 120/120 [02:35<00:00, 1.30s/it] Class Images Instances P R mAP50 mAP50-95: 100% 7/7 [00:07<00:00, 1.07s/it] all 215 429 0.659 0.664 0.677 0.34 Epoch GPU_mem box_loss obj_loss cls_loss Instances Size 9/29 13.9G 0.04338 0.02367 0 11 640: 100% 120/120 [02:33<00:00, 1.28s/it] Class Images Instances P R mAP50 mAP50-95: 100% 7/7 [00:06<00:00, 1.10it/s] all 215 429 0.658 0.683 0.67 0.325 Epoch GPU_mem box_loss obj_loss cls_loss Instances Size 10/29 13.9G 0.04241 0.02331 0 5 640: 100% 120/120 [02:35<00:00, 1.30s/it] Class Images Instances P R mAP50 mAP50-95: 100% 7/7 [00:06<00:00, 1.15it/s] all 215 429 0.681 0.718 0.698 0.339 Epoch GPU_mem box_loss obj_loss cls_loss Instances Size 11/29 13.9G 0.04057 0.02258 0 19 640: 100% 120/120 [02:32<00:00, 1.27s/it] Class Images Instances P R mAP50 mAP50-95: 100% 7/7 [00:07<00:00, 1.03s/it] all 215 429 0.763 0.728 0.751 0.369 Epoch GPU_mem box_loss obj_loss cls_loss Instances Size 12/29 13.9G 0.03943 0.0216 0 12 640: 100% 120/120 [02:39<00:00, 1.33s/it] Class Images Instances P R mAP50 mAP50-95: 100% 7/7 [00:06<00:00, 1.12it/s] all 215 429 0.76 0.718 0.751 0.398 Epoch GPU_mem box_loss obj_loss cls_loss Instances Size 13/29 13.9G 0.03821 0.02181 0 9 640: 100% 120/120 [02:38<00:00, 1.32s/it] Class Images Instances P R mAP50 mAP50-95: 100% 7/7 [00:06<00:00, 1.13it/s] all 215 429 0.739 0.741 0.756 0.393 Epoch GPU_mem box_loss obj_loss cls_loss Instances Size 14/29 13.9G 0.03737 0.02086 0 7 640: 100% 120/120 [02:32<00:00, 1.27s/it] Class Images Instances P R mAP50 mAP50-95: 100% 7/7 [00:06<00:00, 1.03it/s] all 215 429 0.767 0.746 0.766 0.405 Epoch GPU_mem box_loss obj_loss cls_loss Instances Size 15/29 13.9G 0.03638 0.02039 0 9 640: 100% 120/120 [02:39<00:00, 1.33s/it] Class Images Instances P R mAP50 mAP50-95: 100% 7/7 [00:06<00:00, 1.10it/s] all 215 429 0.754 0.736 0.77 0.42 Epoch GPU_mem box_loss obj_loss cls_loss Instances Size 16/29 13.9G 0.03475 0.01999 0 8 640: 100% 120/120 [02:36<00:00, 1.30s/it] Class Images Instances P R mAP50 mAP50-95: 100% 7/7 [00:06<00:00, 1.12it/s] all 215 429 0.748 0.727 0.759 0.426 Epoch GPU_mem box_loss obj_loss cls_loss Instances Size 17/29 13.9G 0.03438 0.01937 0 12 640: 100% 120/120 [02:37<00:00, 1.31s/it] Class Images Instances P R mAP50 mAP50-95: 100% 7/7 [00:07<00:00, 1.01s/it] all 215 429 0.814 0.767 0.803 0.454 Epoch GPU_mem box_loss obj_loss cls_loss Instances Size 18/29 13.9G 0.033 0.01913 0 7 640: 100% 120/120 [02:36<00:00, 1.31s/it] Class Images Instances P R mAP50 mAP50-95: 100% 7/7 [00:05<00:00, 1.24it/s] all 215 429 0.778 0.725 0.783 0.458 Epoch GPU_mem box_loss obj_loss cls_loss Instances Size 19/29 13.9G 0.03239 0.01904 0 12 640: 100% 120/120 [02:37<00:00, 1.31s/it] Class Images Instances P R mAP50 mAP50-95: 100% 7/7 [00:06<00:00, 1.16it/s] all 215 429 0.813 0.75 0.792 0.485 Epoch GPU_mem box_loss obj_loss cls_loss Instances Size 20/29 13.9G 0.03129 0.01844 0 3 640: 100% 120/120 [02:37<00:00, 1.31s/it] Class Images Instances P R mAP50 mAP50-95: 100% 7/7 [00:07<00:00, 1.09s/it] all 215 429 0.78 0.783 0.793 0.461 Epoch GPU_mem box_loss obj_loss cls_loss Instances Size 21/29 13.9G 0.0306 0.0177 0 11 640: 100% 120/120 [02:33<00:00, 1.28s/it] Class Images Instances P R mAP50 mAP50-95: 100% 7/7 [00:07<00:00, 1.12s/it] all 215 429 0.795 0.785 0.788 0.485 Epoch GPU_mem box_loss obj_loss cls_loss Instances Size 22/29 13.9G 0.03001 0.01804 0 8 640: 100% 120/120 [02:33<00:00, 1.28s/it] Class Images Instances P R mAP50 mAP50-95: 100% 7/7 [00:06<00:00, 1.11it/s] all 215 429 0.784 0.774 0.811 0.496 Epoch GPU_mem box_loss obj_loss cls_loss Instances Size 23/29 13.9G 0.02855 0.0171 0 13 640: 100% 120/120 [02:37<00:00, 1.31s/it] Class Images Instances P R mAP50 mAP50-95: 100% 7/7 [00:06<00:00, 1.00it/s] all 215 429 0.793 0.777 0.791 0.5 Epoch GPU_mem box_loss obj_loss cls_loss Instances Size 24/29 13.9G 0.0281 0.0169 0 9 640: 100% 120/120 [02:35<00:00, 1.30s/it] Class Images Instances P R mAP50 mAP50-95: 100% 7/7 [00:06<00:00, 1.08it/s] all 215 429 0.793 0.775 0.811 0.511 Epoch GPU_mem box_loss obj_loss cls_loss Instances Size 25/29 13.9G 0.02731 0.01638 0 8 640: 100% 120/120 [02:38<00:00, 1.32s/it] Class Images Instances P R mAP50 mAP50-95: 100% 7/7 [00:06<00:00, 1.10it/s] all 215 429 0.773 0.785 0.819 0.521 Epoch GPU_mem box_loss obj_loss cls_loss Instances Size 26/29 13.9G 0.02652 0.01663 0 14 640: 100% 120/120 [02:38<00:00, 1.32s/it] Class Images Instances P R mAP50 mAP50-95: 100% 7/7 [00:07<00:00, 1.05s/it] all 215 429 0.835 0.753 0.82 0.527 Epoch GPU_mem box_loss obj_loss cls_loss Instances Size 27/29 13.9G 0.02603 0.01627 0 10 640: 100% 120/120 [02:33<00:00, 1.28s/it] Class Images Instances P R mAP50 mAP50-95: 100% 7/7 [00:06<00:00, 1.15it/s] all 215 429 0.8 0.803 0.816 0.53 Epoch GPU_mem box_loss obj_loss cls_loss Instances Size 28/29 13.9G 0.0252 0.01593 0 11 640: 100% 120/120 [02:42<00:00, 1.35s/it] Class Images Instances P R mAP50 mAP50-95: 100% 7/7 [00:06<00:00, 1.11it/s] all 215 429 0.836 0.783 0.827 0.544 Epoch GPU_mem box_loss obj_loss cls_loss Instances Size 29/29 13.9G 0.02493 0.01545 0 10 640: 100% 120/120 [02:38<00:00, 1.32s/it] Class Images Instances P R mAP50 mAP50-95: 100% 7/7 [00:07<00:00, 1.02s/it] all 215 429 0.831 0.765 0.823 0.548 30 epochs completed in 1.411 hours. Optimizer stripped from runs/train/exp/weights/last.pt, 173.1MB Optimizer stripped from runs/train/exp/weights/best.pt, 173.1MB Validating runs/train/exp/weights/best.pt... Fusing layers... Model summary: 322 layers, 86173414 parameters, 0 gradients, 203.8 GFLOPs Class Images Instances P R mAP50 mAP50-95: 100% 7/7 [00:07<00:00, 1.11s/it] all 215 429 0.832 0.765 0.822 0.548 Results saved to runs/train/exp wandb: Waiting for W&B process to finish... (success). wandb: wandb: Run history: wandb: metrics/mAP_0.5 ▁▃▄▄▅▅▆▆▆▆▆▇▇▇▇▇▇█▇████████████ wandb: metrics/mAP_0.5:0.95 ▁▂▃▃▄▄▄▄▅▅▅▅▆▆▆▆▆▇▇▇▇▇▇▇▇██████ wandb: metrics/precision ▁▂▄▄▆▅▆▅▆▆▆▇▇▇▇▇▇█▇█▇▇▇▇▇▇█████ wandb: metrics/recall ▁▃▄▄▃▄▅▆▆▆▇▇▇▇▇▇▇▇▇▇██▇███▇██▇▇ wandb: train/box_loss █▆▅▄▄▄▃▃▃▃▃▃▃▂▂▂▂▂▂▂▂▂▂▁▁▁▁▁▁▁ wandb: train/cls_loss ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ wandb: train/obj_loss █▆▅▄▄▄▄▄▄▄▄▃▃▃▃▃▂▂▂▂▂▂▂▂▁▁▁▁▁▁ wandb: val/box_loss █▆▆▅▄▄▄▄▃▄▄▃▃▃▃▂▂▂▂▂▂▂▁▁▁▁▁▁▁▁▁ wandb: val/cls_loss ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ wandb: val/obj_loss █▄▄▅▄▅▄▄▃▃▃▂▂▃▂▂▂▁▂▂▂▂▁▁▂▁▁▁▁▁▁ wandb: x/lr0 █▅▂▂▂▂▂▂▂▂▂▂▂▂▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ wandb: x/lr1 ▃▆███▇▇▇▇▆▆▆▆▅▅▅▅▄▄▄▃▃▃▃▂▂▂▂▁▁ wandb: x/lr2 ▃▆███▇▇▇▇▆▆▆▆▅▅▅▅▄▄▄▃▃▃▃▂▂▂▂▁▁ wandb: wandb: Run summary: wandb: best/epoch 29 wandb: best/mAP_0.5 0.82252 wandb: best/mAP_0.5:0.95 0.54824 wandb: best/precision 0.8309 wandb: best/recall 0.76457 wandb: metrics/mAP_0.5 0.82245 wandb: metrics/mAP_0.5:0.95 0.54763 wandb: metrics/precision 0.83163 wandb: metrics/recall 0.76457 wandb: train/box_loss 0.02493 wandb: train/cls_loss 0.0 wandb: train/obj_loss 0.01545 wandb: val/box_loss 0.03227 wandb: val/cls_loss 0.0 wandb: val/obj_loss 0.01359 wandb: x/lr0 0.00076 wandb: x/lr1 0.00076 wandb: x/lr2 0.00076 wandb: wandb: Synced stilted-water-16: https://wandb.ai/stephenkamau/YOLOv5/runs/5cnebn97 wandb: Synced 5 W&B file(s), 337 media file(s), 1 artifact file(s) and 0 other file(s) wandb: Find logs at: ./wandb/run-20221104_191111-5cnebn97/logs
os.listdir("runs/train/exp")
['weights', 'hyp.yaml', 'opt.yaml', 'events.out.tfevents.1667589071.03b5aea99b1a.4696.0', 'labels_correlogram.jpg', 'labels.jpg', 'train_batch0.jpg', 'train_batch1.jpg', 'train_batch2.jpg', 'results.csv', 'val_batch0_pred.jpg', 'val_batch0_labels.jpg', 'val_batch1_labels.jpg', 'val_batch1_pred.jpg', 'val_batch2_pred.jpg', 'val_batch2_labels.jpg', 'F1_curve.png', 'P_curve.png', 'PR_curve.png', 'R_curve.png', 'confusion_matrix.png', 'results.png']
plt.figure(figsize = (10,10))
plt.axis('off')
plt.imshow(plt.imread('runs/train/exp/labels_correlogram.jpg'));
plt.figure(figsize = (10,10))
plt.axis('off')
plt.imshow(plt.imread('runs/train/exp/labels.jpg'));
plt.figure(figsize = (15, 15))
plt.imshow(plt.imread('runs/train/exp/train_batch2.jpg'))
<matplotlib.image.AxesImage at 0x7f9c2052d910>
plt.figure(figsize = (15, 15))
plt.imshow(plt.imread(f'runs/train/{os.listdir("runs/train/")[-1]}/val_batch2_pred.jpg'))
<matplotlib.image.AxesImage at 0x7f9c204a3f90>
plt.figure(figsize = (10, 10))
plt.imshow(plt.imread(f'runs/train/{os.listdir("runs/train/")[-1]}/confusion_matrix.png'))
<matplotlib.image.AxesImage at 0x7f9c20425190>
plt.figure(figsize = (10, 10))
plt.imshow(plt.imread(f'runs/train/{os.listdir("runs/train/")[-1]}/F1_curve.png'))
<matplotlib.image.AxesImage at 0x7f9c20456910>
plt.figure(figsize = (15, 15))
plt.imshow(plt.imread(f'runs/train/{os.listdir("runs/train/")[-1]}/results.png'))
<matplotlib.image.AxesImage at 0x7f9c206d30d0>
!python val.py --weights <PATH TO WEIGHTS> --data <PATH TO DATA CONFIG> --img 640 --iou 0.5 ...
!python val.py --exist-ok --weights runs/train/exp/weights/best.pt --data /content/drive/MyDrive/FIRE/yolo/fire.yaml --img 640 --iou 0.5
val: data=/content/drive/MyDrive/FIRE/yolo/fire.yaml, weights=['runs/train/exp/weights/best.pt'], batch_size=32, imgsz=640, conf_thres=0.001, iou_thres=0.5, max_det=300, task=val, device=, workers=8, single_cls=False, augment=False, verbose=False, save_txt=False, save_hybrid=False, save_conf=False, save_json=False, project=runs/val, name=exp, exist_ok=True, half=False, dnn=False YOLOv5 🚀 v6.2-226-gfde7758 Python-3.7.15 torch-1.12.1+cu113 CUDA:0 (Tesla T4, 15110MiB) Fusing layers... Model summary: 322 layers, 86173414 parameters, 0 gradients, 203.8 GFLOPs val: Scanning '/content/drive/MyDrive/FIRE/yolo/val.cache' images and labels... 218 found, 0 missing, 0 empty, 3 corrupt: 100% 218/218 [00:00<?, ?it/s] val: WARNING ⚠️ /content/drive/MyDrive/FIRE/yolo/images/val/347.jpg: ignoring corrupt image/label: non-normalized or out of bounds coordinates [ 1.0087] val: WARNING ⚠️ /content/drive/MyDrive/FIRE/yolo/images/val/776.jpg: ignoring corrupt image/label: non-normalized or out of bounds coordinates [ 1.136] val: WARNING ⚠️ /content/drive/MyDrive/FIRE/yolo/images/val/MirrorWEBFire1305.jpg: ignoring corrupt image/label: non-normalized or out of bounds coordinates [ 1.1528 1.0056] Class Images Instances P R mAP50 mAP50-95: 100% 7/7 [00:11<00:00, 1.61s/it] all 215 429 0.833 0.765 0.825 0.549 Speed: 0.5ms pre-process, 36.9ms inference, 1.4ms NMS per image at shape (32, 3, 640, 640) Results saved to runs/val/exp
plt.figure(figsize = (10, 10))
plt.imshow(plt.imread(f'runs/val/{os.listdir("runs/val/")[-1]}/confusion_matrix.png'))
<matplotlib.image.AxesImage at 0x7f9c20364990>
plt.figure(figsize = (10, 10))
plt.imshow(plt.imread(f'runs/val/{os.listdir("runs/val/")[-1]}/F1_curve.png'))
<matplotlib.image.AxesImage at 0x7f9c202d8610>
plt.figure(figsize = (10, 10))
plt.imshow(plt.imread(f'runs/train/{os.listdir("runs/val/")[-1]}/val_batch2_pred.jpg'))
<matplotlib.image.AxesImage at 0x7f9c20253f50>
torch.load to load the model or detect.py file and paass the image path you want eg.!python detect.py --source <IMG PATH> --weights <WEIGHTS PAHT> --img 640 ..
BEST_WGHT = f'/content/drive/MyDrive/FIRE/yolo/yolov5/runs/train/exp/weights/best.pt'
import torch
model = torch.hub.load('ultralytics/yolov5', 'custom', path="runs/train/exp/weights/best.pt", force_reload=True)
Downloading: "https://github.com/ultralytics/yolov5/zipball/master" to /root/.cache/torch/hub/master.zip YOLOv5 🚀 2022-11-4 Python-3.7.15 torch-1.12.1+cu113 CUDA:0 (Tesla T4, 15110MiB) Fusing layers... Model summary: 322 layers, 86173414 parameters, 0 gradients, 203.8 GFLOPs Adding AutoShape...
# model
test1 = model("/content/drive/MyDrive/FIRE/images/MirrorWEBSmoke1318.jpg")
test1.show()
!python detect.py --source /content/drive/MyDrive/FIRE/images/MirrorWEBSmoke1318.jpg --weights runs/train/exp/weights/best.pt --img 640
detect: weights=['runs/train/exp/weights/best.pt'], source=/content/drive/MyDrive/FIRE/images/MirrorWEBSmoke1318.jpg, data=data/coco128.yaml, imgsz=[640, 640], conf_thres=0.25, iou_thres=0.45, max_det=1000, device=, view_img=False, save_txt=False, save_conf=False, save_crop=False, nosave=False, classes=None, agnostic_nms=False, augment=False, visualize=False, update=False, project=runs/detect, name=exp, exist_ok=False, line_thickness=3, hide_labels=False, hide_conf=False, half=False, dnn=False, vid_stride=1 YOLOv5 🚀 v6.2-226-gfde7758 Python-3.7.15 torch-1.12.1+cu113 CUDA:0 (Tesla T4, 15110MiB) Fusing layers... Model summary: 322 layers, 86173414 parameters, 0 gradients, 203.8 GFLOPs image 1/1 /content/drive/MyDrive/FIRE/images/MirrorWEBSmoke1318.jpg: 480x640 3 Fires, 72.3ms Speed: 0.6ms pre-process, 72.3ms inference, 1.5ms NMS per image at shape (1, 3, 640, 640) Results saved to runs/detect/exp
os.listdir("runs/detect/exp")
['MirrorWEBSmoke1318.jpg']
plt.figure(figsize = (10, 10))
plt.imshow(plt.imread(f'runs/detect/exp/MirrorWEBSmoke1318.jpg'))
<matplotlib.image.AxesImage at 0x7f9c0bc23690>
test2 = model("/content/drive/MyDrive/FIRE/images/WEBFire977.jpg")
plt.imshow(np.squeeze(test2.render()))
<matplotlib.image.AxesImage at 0x7f9c0a36d510>
!pwd
/content/drive/MyDrive/FIRE/yolo/yolov5
# !python detect.py --source /content/input.mp4 --weights runs/train/exp/weights/best.pt --conf 0.2
# Inferencing using this code takes alot of time since you have to extract each frame and then pass to model before visualizing
# import cv2
# vidcap = cv2.VideoCapture('runs/detect/exp8/input.mp4')
# success,image = vidcap.read()
# images = []
# while success:
# success,image = vidcap.read()
# if success:
# image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
# images.append(image)
# len(images)
# from matplotlib import animation, rc
# import matplotlib.pyplot as plt
# import matplotlib
# matplotlib.rcParams['animation.embed_limit'] = 2**128
# rc('animation', html='jshtml')
# def create_animation(ims):
# fig = plt.figure(figsize=(9, 9))
# plt.axis('off')
# im = plt.imshow(ims[0])
# def animate_func(i):
# im.set_array(ims[i])
# return [im]
# return animation.FuncAnimation(fig, animate_func, frames = len(ims), interval = 1000//12)
# create_animation(images)
# ISSUES:
# ....Fire doesn’t have any specified shape or size and even at times, varies in color,
# Hence achieving a high accuracy in its detection is a difficult task.